﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Creventive.Wpf.ShellFactory.Modules;
using Creventive.Wpf.ShellFactory.Services;
using Creventive.Wpf.ShellFactory.Utility;

namespace MultiViewWithLogin.Infrastructure.Shell
{
    /// <summary>
    ///   A controller for the widget views extension.
    /// </summary>
    public class WidgetViewsController
    {
        private HashSet<Widgets> extensions = new HashSet<Widgets>();
        private ObservableSet<WidgetViewSource> viewReferences = new ObservableSet<WidgetViewSource>();
        private ReadOnlyObservableCollection<WidgetViewSource> viewSourcesView;

        /// <summary>
        ///   Initializes a new instance of the <see cref = "WidgetViewsController" /> class.
        /// </summary>
        public WidgetViewsController()
        {
            this.viewSourcesView = new ReadOnlyObservableCollection<WidgetViewSource>(this.viewReferences);
            IApplicationModuleService applicationModuleService = ServiceContainer.Default.EnsureService<IApplicationModuleService>();
            foreach (var module in applicationModuleService.ApplicationModules)
            {
                var extension = Widgets.GetExtension(module);
                if (extension != null)
                {
                    this.extensions.Add(extension);
                    extension.ViewSources.CollectionChanged += this.ViewReferences_CollectionChanged;
                }
            }
            this.Reset();
        }

        /// <summary>
        ///   Gets the view sources that represents widget views.
        /// </summary>
        /// <value>The view sources.</value>
        public ReadOnlyObservableCollection<WidgetViewSource> ViewSources
        {
            get { return this.viewSourcesView; }
        }

        /// <summary>
        ///   Resets the controller, ensuring all widget view references have been updated.
        /// </summary>
        public void Reset()
        {
            int baseOrder = 1;
            var sourceArray = this.extensions
                .SelectMany(e => e.ViewSources)
                .OrderBy(r =>
                         {
                             var sortOrder = r.SortOrder;
                             if (sortOrder > 0)
                             {
                                 baseOrder = sortOrder;
                                 return sortOrder;
                             }
                             else
                             {
                                 baseOrder++;
                                 return baseOrder;
                             }
                         }).ToArray();
            this.viewReferences.Synchronize(sourceArray);
        }

        private void ViewReferences_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.Reset();
        }
    }
}